brisky-struct
An observable data structure
- Deep memory efficient prototypes
- Every value is observable
- Serializable references
- Fast reactive state management. Inspired by virtual-dom tree-diffing algorithms and merkle-trees
- Powerful query syntax
- Fast emitters
- Async helpers, work with generators, promises and iterators
- Low footprint (6kb gzipped)
CRUD
Create
const struct = require('brisky-struct')
const root = struct.create({ firstKey: 'value' })
Serialize
root.serialize()
Set
⚠ Default behaviour is merge.
root.set({ second: { subKey: 'subValue' } })
root.serialize()
Get
root.get('second').serialize()
Keys
root.keys()
Remove
root.set({ firstKey: null })
root.get('firstKey')
root.keys()
Compute
const sub = root.get(['second', 'subKey'])
sub.compute()
Navigate
Key
sub.key
Path
sub.path()
Parent
sub.parent().key
sub.parent().serialize()
Root
sub.root().serialize()
sub.root() === root
Listen
On
Default listener
var results = []
root.set({ on: val => results.push(val) })
root.set({ third: 3 })
results
Data listener
root.set({ on: { data: val => results.push(val) } })
root.set({ fourth: 4 })
results
Named data listener
⚠ Only named listeners won't override existing listeners. Notice that fifth
appears twice in the results array.
root.set({ on: { data: { namedListener: val => results.push(val) } } })
root.set({ fifth: 5 })
results
On as a method
results = []
const third = root.get('third')
third.on(val => results.push(val))
third.set('changed')
results
root.set({ third: 'again' })
results
Once
Once as a method
results = []
const fourth = root.get('fourth')
fourth.once('four', val => results.push(val))
fourth.set('will be ignored')
results
fourth.set('four')
results
Once as a promise
results = []
fourth.once().then(val => results.push(val))
fourth.set('changed')
results
fourth.set('will be ignored')
results
Emit
⚠ Events fired on a path can be listened only at exact same path.
const errors = []
root.on('error', err => errors.push(err))
root.emit('error', 'satellites are not aligned')
errors
sub.once('error', err => errors.push(err))
sub.emit('error', 'splines are not reticulated')
errors
More about get and set
Get with set
Second parameter of get is a default value for the path.
⚠ It'll be set
and returned in absence of given path otherwise it'll be ignored.
root.get('firstKey', 'newValue').compute()
root.get('firstKey').compute()
root.get('fifth', 'newValue').compute()
Get a path with methods
⚠ Available methods are root
, parent
and compute
.
root.get(['firstKey', 'compute'])
root.get(['second', 'subKey', 'parent']).serialize()
sub.get(['root', 'fifth', 'compute'])
Set without merge (reset)
Third parameter of set is a reset flag.
⚠ Second parameter is a stamp, will come to our plate on further chapters.
const second = root.get('second')
second.set({ newSubKey: 'newSubValue' })
second.serialize()
second.set({ onlySubKey: 'onlySubValue' }, void 0, true)
second.serialize()
Master and branches
const master = struct.create({
movies: {
tt0130827: {
year: 1998,
imdb: 7.7,
title: 'Run Lola Run'
},
tt0301357: {
year: 2003,
imdb: 7.7,
title: 'Good Bye Lenin'
},
tt0408777: {
year: 2004,
imdb: 7.5,
title: 'The Edukators'
}
}
})
const branchM = master.create({
userName:'Mustafa',
movies: {
tt0130827: { favourite: true },
tt0408777: { favourite: true }
}
})
const branchJ = master.create({
userName:'Jim',
movies: {
tt0301357: { favourite: true }
}
})
master.get('userName')
branchM.get(['movies', 'tt0408777']).serialize()
branchJ.get(['movies', 'tt0408777']).serialize()
master.get(['movies', 'tt0408777']).serialize()
master.get(['movies', 'tt0130827', 'rating'], 'R')
branchJ.get(['movies', 'tt0130827', 'rating', 'compute'])
branchM.get(['movies', 'tt0130827', 'rating', 'compute'])
branchJ.get(['movies', 'tt0130827', 'rating']).set('G')
branchM.get(['movies', 'tt0130827', 'rating', 'compute'])
master.get(['movies', 'tt0130827', 'rating']).set('PG')
branchM.get(['movies', 'tt0130827', 'rating', 'compute'])
branchJ.get(['movies', 'tt0130827', 'rating', 'compute'])